<?php
namespace PsiFramework\Classes\Util\UI;

import("Classes.Util.UI.Printer");
import("Classes.Factory.DAOFactory");

use \PsiFramework\Classes\Model\Object;
use \PsiFramework\Classes\Factory\DAOFactory;
use \PsiFramework\Classes\Util\Manager\ApplicationManager;
use \PsiFramework\Classes\Util\UI\LanguageManager;
use \PsiFramework\Classes\Util\UI\Printer;
use \PsiFramework\Classes\Util\UI\TemplateManager;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * Classe de gestion des fonctions d'interface HTML
 *
 * @package Util.UI
 */
class HTML
{

    public static function linkHref(
        /*string*/ $link,
        /*boolean*/ $insertIndex=true
    )
    {

        $okLink = '';

        if (!isNullOrEmptyString($link)) {
            if (substr($link, 0, 7) !== "http://" && $link != '#' ) {
                $baseLink = '' ;
                if ($insertIndex) {
                    $baseLink = "index.php" ;
                }

                $app = ApplicationManager::getInstance()->getApplication();
                if ($app->insertAppParameter) {
                    $appName = $app->getName();
                    $okLink .= "application=".$appName ;
                    if (!isNullOrEmptyString($link)) {
                        $okLink .= '&' ;
                    }
                }

                if (!isNullOrEmptyString($link)) {
                    $okLink .= $link ;
                }

                if (!isNullOrEmptyString($okLink)) {
                    $okLink = $baseLink . '?' . $okLink ;
                } else {
                    $okLink = $baseLink ;
                }

            } else {
                $okLink = $link ;
            }
        } else {
            if ($insertIndex) {
                $okLink = 'index.php' ;
            } else {
                $okLink = './' ;
            }
            
            $app = ApplicationManager::getInstance()->getApplication();
            if ($app->insertAppParameter) {
            	$appName = $app->getName();
            	$okLink .= "?application=".$appName ;
            }
        }

        return $okLink ;
    }

    /**
     * Function that returns the html code for a link
     *
     * @param     string $text         the text to display
     * @param     string $link         the link
     * @param     array  $options      the options
     * @param     bool   $popup        open as popup
     * @param     array  $popupOptions the popup options
     * @return    string    the link
     */
    public static function link(
        /*string*/ $text,
        /*string*/ $link = null,
        /*array*/  $options=null
    )
    {
        
        $link = Printer::getText(self::linkHref($link));
        
        $strOptions = '' ;
        if (!is_null($options)) {
            foreach ($options as $optionName=>$optionValue) {
                $strOptions .= $optionName . '="'.$optionValue.'" ' ;
            }
        }
        
        $linkTag  = '<a href="'.$link.'" '.$strOptions.'>'.Printer::getText($text).'</a>' ;
        
        return $linkTag;
    }

    public static function addValidator()
    {

        $languageManager = LanguageManager::getInstance();
        $localisedConfig = $languageManager->getLocalisedConfig();

        $js  = '$(document).ready(function() {' . "\n" ;
        $js .= '    $(".psiForm").validate({' . "\n" ;
        $js .= '        messages: {' . "\n" ;

        $messages = $localisedConfig->validationMessages ;
        $first = true ;
        foreach ($messages as $key=>$value) {
            if (!$first) {
                $js .= ", \n" ;
            } else {
                $first = false ;
            }
            $js .= '            '.$key.':"'.$value.'"' ;
        }
        $js .= "\n" ;
        $js .= '        }' . "\n" ;
        $js .= '    });' . "\n" ;
        $js .= '});' . "\n" ;

        $templateManager = TemplateManager::getInstance();
        $templateManager->addRemoteScript(
            'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'
        );
        $templateManager->addRemoteScript(
            'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js'
        );
        $templateManager->addRemoteScript(
            './Scripts/jquery.validate.js'
        );

        $templateManager->addLitteralScript($js);
    }

    /**
     * Returns the javascript code for the autocomplete function
     *
     * @param     string     $name
     * @param     string     $service
     * @param     array     $options
     */
    public static function addAutoComplete(
        /*string*/ $labelName,
        /*string*/ $idName,
        /*string*/ $service=null,
        /*array*/  $options=null
    )
    {
        if (is_null($service)) {
            $service = 'List' ;
        }

        $js  = '$(document).ready(function() {' . "\n" ;
        $js  = '    $("#'.$labelName.'").autocomplete({' . "\n" ;
        $js .= '        source: "?service='.$service.'&format=json",' . "\n" ;
        $js .= '        select: function(event, ui) {' . "\n" ;
        $js .= '            $("#'.$labelName.'").val(ui.item.label);' . "\n" ;
        $js .= '            $("#'.$idName.'").val(ui.item.id);' . "\n" ;

        if (!is_null($options)) {
            foreach ($options as $value) {
                $js .= '            '.$value.' ;' . "\n" ;
            }
        }

        $js .= '        }' . "\n" ;
        $js .= '    });' . "\n" ;
        $js .= '});' . "\n" ;

        $templateManager = TemplateManager::getInstance();
        $templateManager->addRemoteScript(
            'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'
        );
        $templateManager->addRemoteScript(
            'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js'
        );

        $templateManager->addLitteralScript($js);
    }

    /**
     * Return the html code for a field
     *
     * @param string $name
     * @param string $label
     * @param string $input
     * @param array $options
     */
    public static function field(
        /*string*/ $name,
        /*string*/ $label,
        /*string*/ $input,
        /*array*/  $options=null
    )
    {
        $classDeclaration = '' ;
        $styleDeclaration = '' ;
        $parentTag = 'span' ;

        if (!is_null($options)) {
            if (array_key_exists('class', $options)
                && !isNullOrEmptyString($options['class'])
            ) {
                $classDeclaration = ' class="'.$options['class'].'"' ;
            }
            if (array_key_exists('style', $options)
                && !isNullOrEmptyString($options['style'])
            ) {
                $styleDeclaration = ' class="'.$options['style'].'"' ;
            }
            if (array_key_exists('tag', $options)
                && !isNullOrEmptyString($options['tag'])
            ) {
                $parentTag = $options['tag'] ;
            }
        }

        $field  = '<'.$parentTag.$classDeclaration.$styleDeclaration.' >'."\n" ;
        $field .= '    <label for="'.$name.'">'."\n" ;
        $field .= '        '.$label."\n" ;
        $field .= '    </label>'."\n" ;
        $field .= '    '.$input."\n" ;
        $field .= '</span>'."\n" ;

        return $field ;
    }

    /**
     * Function that returns the html code for an autocomplete text input
     *
     * @param     string     $name        the name of the field
     * @param     Object     $value        the value
     */
    public static function autocompleteInput(
        /*string*/ $name,
        Object $value=null
    )
    {
        $stringValue = '' ;
        $id = '' ;
        if (!is_null($value)) {
            $stringValue = $value->toString();
            $id = $value->getId();
        }

        $html  = self::textInput(
            $name.'_name',
            $stringValue,
            array('type'=>'text', 'class'=>'fieldTypeSelecter')
        );
        $html .= self::textInput(
            $name.'_id',
            $id,
            array('type'=>'hidden', 'class'=>'inputId')
        );

        return $html ;
    }

    /**
     * Function that returns the html code for an input
     *
     * @param     string    $name        the name of the input
     * @param     string    $value        the value of the input
     * @param    string    $options    the options for the input
     * @return    string    the input
     */
    public static function input(
        /*string*/ $name,
        /*string*/ $value,
        /*array*/  $options=array()
    )
    {

        if (is_null($options)) {
            $options=array();
        }
        if (!array_key_exists('class', $options)
            || isNullOrEmptyString($options['class'])
        ) {
            $options['type'] = 'text' ;
        }

        $options['id'] = $name ;
        $options['name'] = $name ;
        $options['value'] = $value ;

        $html  = '<input' ;
        foreach ($options as $key=>$value) {
            $html .= ' '.Printer::getText($key).'="'.
                         Printer::getText($value).'"';
        }
        $html .= ' />' . "\n" ;

        return $html ;
    }

    /**
     * Function that returns the html code for a text input
     *
     * @param     string    $name        the name of the input
     * @param     string    $value        the value of the input
     * @param    array    $options    the options for the input
     * @return    string    the text input
     */
    public static function textInput(
        /*string*/ $name,
        /*string*/ $value,
        /*array*/  $options=array()
    )
    {
        if (is_null($options)) {
            $options=array();
        }
        $options['type'] = 'text' ;
        return self::input($name, $value, $options);
    }

    /**
     * Function that returns the html code for a text
     * input for an object attribute
     *
     * @param    Object   $object        the object
     * @param    string   $attName    the name of the object attribute
     * @param    array    $options    the options for the input
     * @return   string   the text input
     */
    public static function objectTextInput(
        Object $object,
        /*string*/ $attName,
        /*array*/ $options=array()
    )
    {
        $objectParameters
            = ApplicationManager::getInstance()
                ->getApplication()
                ->getObjectParameter($object->getObjectName());
        $att = $objectParameters->getParameter();
        $getter = $att->getter ;
        return self::textInput($att->column, $object->$getter(), $options);
    }

    /**
     * Function that returns the html code for a select
     *
     * @param    string    $name        the name of the select
     * @param    string    $values        the value of the select
     * @param    string    $options    the options of the select
     * @return    string    the select
     */
    public static function selectInput(
        /*string*/ $name,
        /*array*/ $values,
        /*array*/ $options=null
    )
    {
        $input =  '<select '.
                      'name="'.Printer::getText($name).'" '.
                      'id="'.Printer::getText($name).'" '.
                  '>' . "\n" ;
        foreach ($values as $value) {
            $selected
                = (isset($value['selected'])) ?
                    $value['selected'] : false ;
            $input .= '    <option '.
                              'value="'.
                                Printer::getText($value['value']).
                              '"' ;
            if ($selected) {
                $input .= ' selected="selected"' ;
            }
            $input .= '>'.Printer::getText($value['text']).'</option>' . "\n" ;
        }
        $input .= '</select>' . "\n" ;
        return $input ;
    }

    /**
     * Returns an array for a select input
     *
     * @param string $type
     * @param mixed $selected
     * @param string $valueFunction
     * @param string $textFunction
     * @param boolean $insertBlank
     * @return Array
     */
    public static function getArrayForSelect(
        /*string*/  $type,
        /*mixed*/   $selected,
        /*string*/  $valueFunction="getId",
        /*string*/  $textFunction="toString",
        /*boolean*/ $insertBlank=false
    )
    {

        $dao = DAOFactory::getDAO($type);
        $values = array();

        if ($insertBlank) {
            $values[] = array('value'=>'', 'text'=>'');
        }

        $list = $dao->retrieveAll();
        foreach ($list as $obj) {
            $currValue = array();
            $currValue['value'] = $obj->$valueFunction();
            $currValue['text'] = $obj->$textFunction();
            if ($obj->$valueFunction() == $selected) {
                $currValue['selected'] = true ;
            }
            $values[] = $currValue ;
        }

        return $values ;
    }

    /**
     * Function that returns the html code for a select
     * input for an object attribute
     *
     * @param     Object    $object        the object
     * @param     string    $attName    the name of the object attribute
     * @param    string    $options    the options for the input
     * @return    string    the select input
     */
    public static function objectSelectInput(
        Object     $object,
        /*string*/ $attName,
        /*array*/  $options=null
    )
    {
        $objectParameters
            = ApplicationManager::getInstance()
                ->getApplication()
                ->getObjectParameter($object->getObjectName());
        $att = $objectParameters->getParameter();
        $getter = $att->getter ;
        $value = $object->$getter();
        $selected = ($value != null)?$value->getId():null ;

        $type = $att->type ;
        $values
            = self::getArrayForSelect(
                $type,
                $selected,
                'getId',
                'toString',
                true
            );

        return self::selectInput($att->column, $values, $options);
    }

    /**
     * Function that returns the html code for a set of radiobuttons
     *
     * @param    string    $name        the name of the radiobuttons
     * @param    string    $values        the values of the radiobuttons
     * @param    string    $options    the options of the radiobuttons
     * @return    string    the select
     */
    public static function radiobuttonsInput(
        /*string*/ $name,
        /*array*/ $values,
        /*array*/ $options=null
    )
    {
        $input =  '' ;
        foreach ($values as $value) {
            $selected
                = (isset($value['selected'])) ?
                    $value['selected'] : false ;
            $input .= '<input '.
                            'type="radio" '.
                            'name="'.Printer::getText($name).'" '.
                            'value="'.Printer::getText($value['value']).'"' ;
            if ($selected) {
                $input .= ' checked="checked"' ;
            }
            $input .= '/>'.Printer::getText($value['text']) . "\n" ;
        }
        return $input ;
    }

    /**
     * Function that returns the html code for a radiobuttons
     * input for an object attribute
     *
     * @param     Object    $object     the object
     * @param     string    $attName    the name of the object attribute
     * @param     string    $options    the options for the input
     * @return    string    the select input
     */
    public static function objectRadiobuttonsInput(
        Object $object,
        /*string*/ $attName,
        /*array*/ $options=null
    )
    {
        $objectParameters
            = ApplicationManager::getInstance()
                ->getApplication()
                ->getObjectParameter($object->getObjectName());
        $att = $objectParameters->getParameter();
        $getter = $att->getter ;
        $value = $object->$getter();
        $selected = ($value != null)?$value->getId():null ;

        $type = $att->type ;
        $values
            = self::getArrayForSelect(
                $type,
                $selected,
                'getId',
                'toString',
                false
            );

        return self::radiobuttonsInput($att->column, $values, $options);
    }

    /**
     * Function that returns the html code for a button which
     * type is passed to the function
     *
     * @param     string     $type the type of the button
     * @param     string     $value the value of the button
     * @param    string    $options    the options for the input
     * @return    string    the button input
     */
    protected static function abstractButton(
        /*string*/ $type,
        /*string*/ $value,
        /*array*/ $options=null
    )
    {
        $button  = '<input type="'.Printer::getText($type).'" ' ;
        if ($options != null) {
            foreach ($options as $name=>$value) {
                $button .= 
                    Printer::getText($name).'="'.
                    Printer::getText($value).'" ' ;
            }
        }
        $button .= 'value="'.Printer::getText($value).'" />' . "\n" ;

        return $button ;
    }

    /**
     * Function that returns the html code for a submit button
     *
     * @param     string     $value the value of the button
     * @param    string    $options    the options for the input
     * @return    string    the button input
     */
    public static function submitButton(
        /*string*/ $value,
        /*array*/ $options=null
    )
    {
        return self::abstractButton("submit", $value, $options);
    }

    /**
     * Function that returns the html code for a cancel button
     *
     * @param     string     $value the value of the button
     * @param    string    $options    the options for the input
     * @return    string    the button input
     */
    public static function cancelButton(
        /*string*/ $value,
        /*array*/ $options=null
    )
    {
        if ($options == null) {
            $options = array();
        }
        $options['name'] = 'cancel' ;
        return self::button($value, $options);
    }

    /**
     * Function that returns the html code for a button
     *
     * @param     string     $value the value of the button
     * @param    string    $options    the options for the input
     * @return    string    the button input
     */
    public static function button(/*string*/ $value, /*array*/ $options=null)
    {
        return self::abstractButton("button", $value, $options);
    }
}
